<?php 
namespace App\Library\Services;

use App\Library\Utilities\Config;
use ReflectionMethod;

class RouterService
{
    protected $routes = [];
    protected $routeCache = [];
    protected $baseNamespace = '\\App\\Models\\'; // 控制器的基本命名空间

    // 加载路由配置
    public function loadRoutes()
    {
        if (empty($this->routeCache)) {
            // 从 Config 中动态获取整个路由配置
            $routes = Config::get('routes'); // 获取整个路由配置
            
            // 获取 Web 和 API 路由配置
            $this->routeCache['web'] = $routes['web'] ?? [];
            $this->routeCache['api'] = $routes['api'] ?? [];
        }
        return $this->routeCache;
    }

    // 处理请求
    public function handleRequest($type, $method, $uri)
    {
        try {
            // 加载路由配置
            $routes = $this->loadRoutes()[$type];
        
            // 遍历路由进行匹配
            foreach ($routes[$method] ?? [] as $priority => $route) {
                // 解析路由并匹配
                $params = $this->matchRoute($priority, $uri);

                if ($params !== false) {
                    // 执行中间件
                    $this->executeMiddleware($route['middleware'] ?? []);
        
                    // 动态调用控制器方法
                    return $this->callControllerAction($route['action'], $params);
                }
            }
        
            throw new \Exception("No matching route found for '$method $uri'.", 404);
        } catch (\Exception $e) {
            echo "Error: " . $e->getMessage() . "<br>";
            echo "Trace: " . nl2br($e->getTraceAsString()) . "<br>";
        }
    }

    // 匹配路由和 URI 部分
    protected function matchRoute($routePattern, $uri)
    {
        // 将路由模式和 URI 按 "/" 分割
        $routeParts = explode('/', trim($routePattern, '/'));
        $uriParts = explode('/', trim($uri, '/'));

        // 检查数量是否一致
        if (count($routeParts) != count($uriParts)) {
            return false; // 路由和 URI 部分数量不一致
        }

        // 用于存储匹配的参数
        $params = [];
        
        foreach ($routeParts as $index => $part) {
            if ($this->isPlaceholder($part)) {
                // 如果是占位符，如 {module}, {controller}, {action} 等
                $paramName = $this->getParameterName($part);
                $params[$paramName] = $uriParts[$index];
            } elseif ($part != $uriParts[$index]) {
                // 如果不是占位符且不匹配，返回 false
                return false;
            }
        }


        
        // 处理可选参数，如 {id?}
        if (isset($params['id']) && empty($params['id'])) {
            unset($params['id']); // 如果 id 为空且是可选的，移除该参数
        }

        return $params; // 返回匹配的参数
    }

    // 检查一个部分是否是占位符
    protected function isPlaceholder($part)
    {
        return strpos($part, '{') === 0 && strpos($part, '}') === strlen($part) - 1;
    }

    // 获取占位符的参数名
    protected function getParameterName($part)
    {
        return trim($part, '{}'); // 去掉大括号
    }

    // 执行多个中间件
    protected function executeMiddleware($middleware)
    {
        foreach ($middleware as $mw) {
            // 检查中间件类是否存在，并正确实例化
            if (class_exists($mw)) {
                $mwObject = new $mw();
                $mwObject->handle();
            } else {
                throw new \Exception("Middleware class $mw not found.", 500);
            }
        }
    }

    // 动态调用控制器方法
    // 动态调用控制器方法
    protected function callControllerAction($action, $params)
    {
        $module = $params['module'] ?? 'default'; // 提取模块名
        $controller = $params['controller'] ?? 'default'; // 提取控制器名
        $action = $action ?? 'index'; // 提取动作名
    
        // 检查控制器是否包含 "Controller" 后缀
        $controller = ucfirst($controller);
        if (!str_ends_with($controller, 'Controller')) {
            $controller .= 'Controller';
        }
    
        // 拼接完整的命名空间
        $controllerClass = "\\App\\Models\\" . ucfirst($module) . "\\" . $controller;

    
        // 检查控制器类是否存在
        if (!class_exists($controllerClass)) {
            throw new \Exception("Controller $controllerClass not found.");
        }
    
        // 实例化控制器并调用动作
        $controllerInstance = new $controllerClass();
        if (!method_exists($controllerInstance, $action)) {
            throw new \Exception("Action $action not found in controller $controllerClass.");
        }
    
        // 获取 ID 参数并确保处理它
        $id = $params['id'] ?? null; // 从参数中获取 id，优先使用 id 而非 id?
        if (isset($params['id?'])) {
            $id = $params['id?'];  // 如果 id? 存在，则将其赋值给 id
        }
    
        return call_user_func_array([$controllerInstance, $action], [$id]);
    }

}
